{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "91844b18",
   "metadata": {},
   "source": [
    "## 运行一个简单的策略"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c7572bed",
   "metadata": {},
   "source": [
    "# 基于掘金平台的量化策略实现\n",
    "\n",
    "\n",
    "## 软件的安装注意事项\n",
    "\n",
    "安装常见问题汇总：\n",
    "\n",
    "https://www.myquant.cn/docs/gm3_faq/154?\n",
    "\n",
    "以anaconda为环境，如果在已经装好gm库，并且配置好python路径后，有时会因为python包的版本不匹配出现各种问题\n",
    "解决这种问题的最根本的办法是在anaconda创建新的虚拟环境，然后在干净的虚拟环境中安装gm，这样通常都能解决问题。\n",
    "\n",
    "\n",
    "anaconda虚拟环境的创建与使用方法：\n",
    "\n",
    "https://baijiahao.baidu.com/s?id=1633371123637717203&wfr=spider&for=pc\n",
    "\n",
    "\n",
    "\n",
    "## 第一个策略的编写与运行\n",
    "\n",
    "https://www.myquant.cn/docs/python/python_basic\n",
    "\n",
    "## 定时任务——最简单的策略模式\n",
    "\n",
    "https://www.myquant.cn/docs/python/quickstart#7ad6b17bec4c98b8\n",
    "\n",
    "* 初始化函数 ini\n",
    "\n",
    "* 定时运行函数 elgo\n",
    "\n",
    "不同的函数运行次数是不同的！\n",
    "\n",
    "init 函数最开始运行一次，其他函数运行次数由相关函数决定\n",
    "\n",
    "\n",
    "### 掘金平台下的股票代码\n",
    "\n",
    "\n",
    "上交所 SHSE\n",
    "\n",
    "深交所 SZSE\n",
    "\n",
    "### 不同的交易函数\n",
    "\n",
    "\n",
    "order_volume - 按指定量委托\n",
    "\n",
    "order_value - 按指定价值委托\n",
    "\n",
    "order_percent - 按总资产指定比例委托\n",
    "\n",
    "order_target_volume - 调仓到目标持仓量（可用来卖出）\n",
    "\n",
    "order_target_value - 调仓到目标持仓额\n",
    "\n",
    "order_target_percent - 调仓到目标持仓比例（总资产的比例）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "625bf31d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# coding=utf-8\n",
    "from __future__ import print_function, absolute_import\n",
    "from gm.api import *\n",
    "def init(context):\n",
    "    # 每天14:50 定时执行algo任务,\n",
    "    # algo执行定时任务函数，只能传context参数\n",
    "    # date_rule执行频率，目前暂时支持1d、1w、1m，其中1w、1m仅用于回测，实时模式1d以上的频率，需要在algo判断日期\n",
    "    # time_rule执行时间， 注意多个定时任务设置同一个时间点，前面的定时任务会被后面的覆盖\n",
    "    schedule(schedule_func=algo, date_rule='1d', time_rule='14:50:00')\n",
    "def algo(context):\n",
    "    # 以市价购买200股浦发银行股票， price在市价类型不生效\n",
    "    order_volume(symbol='SHSE.600000', volume=200, side=OrderSide_Buy,\n",
    "                 order_type=OrderType_Market, position_effect=PositionEffect_Open, price=0)\n",
    "# 查看最终的回测结果\n",
    "def on_backtest_finished(context, indicator):\n",
    "    print(indicator)\n",
    "if __name__ == '__main__':\n",
    "    '''\n",
    "        strategy_id策略ID, 由系统生成\n",
    "        filename文件名, 请与本文件名保持一致\n",
    "        mode运行模式, 实时模式:MODE_LIVE回测模式:MODE_BACKTEST\n",
    "        token绑定计算机的ID, 可在系统设置-密钥管理中生成\n",
    "        backtest_start_time回测开始时间\n",
    "        backtest_end_time回测结束时间\n",
    "        backtest_adjust股票复权方式, 不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST\n",
    "        backtest_initial_cash回测初始资金\n",
    "        backtest_commission_ratio回测佣金比例\n",
    "        backtest_slippage_ratio回测滑点比例\n",
    "    '''\n",
    "    run(strategy_id='strategy_id',\n",
    "        filename='main.py',\n",
    "        mode=MODE_BACKTEST,\n",
    "        token='token_id',\n",
    "        backtest_start_time='2020-11-01 08:00:00',\n",
    "        backtest_end_time='2020-11-10 16:00:00',\n",
    "        backtest_adjust=ADJUST_PREV,\n",
    "        backtest_initial_cash=10000000,\n",
    "        backtest_commission_ratio=0.0001,\n",
    "        backtest_slippage_ratio=0.0001)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bd33d4f1",
   "metadata": {},
   "source": [
    "## classwork1\n",
    "\n",
    "* 请找到贵州茅台股票的代码，并在2012年第一个交易日开始每天买入100股，直至钱花光，看20200101的收益（order_volume）\n",
    "\n",
    "* 并在2012年第一个交易日开始每天买入100000金额的贵州茅台股票，看20200101的收益 （order_value）\n",
    "\n",
    "* 请找到贵州茅台股票的代码，并在2012年第一个交易日开始保持仓位500股贵州茅台，直至钱花光，看20200101的收益 （order_target_volume）\n",
    "\n",
    "* 在2020-11-01日购买两只股票：SHSE.600000,SZSE.000001，各购买50% 看一个星期后的收益（order_percent）\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fc55a2dc",
   "metadata": {},
   "source": [
    "## 数据事件驱动策略与相关函数\n",
    "\n",
    "https://www.myquant.cn/docs/python/quickstart#7ad6b17bec4c98b8\n",
    "\n",
    "* 数据事件驱动;时间序列数据事件驱动;多个标的数据事件驱动\n",
    "\n",
    "整个策略需要三步:\n",
    "\n",
    "1，设置初始化函数: init, 使用subscribe函数进行数据订阅\n",
    "\n",
    "(这里的数据订阅本质上就是把若干bar中的数据缓存到内存里来避免重复获取。对于通过调取云数据来实现策略的程序，数据获取时间通常占了大头，因此使用subscribe能够避免数据的重复调取，极大的提升策略运行时间)\n",
    "\n",
    "2，实现一个函数: on_bar, 来根据数据推送进行逻辑处理,\n",
    "\n",
    "3，执行策略\n",
    "\n",
    "* subscribe中的count\n",
    "\n",
    "\n",
    "* current - 查询当前行情快照\n",
    "\n",
    "https://www.myquant.cn/docs/python/python_select_api#5b1e04299f7d9a3b\n",
    "\n",
    "\n",
    "* context \n",
    "\n",
    "context是策略的全局变量，此变量既包含了特定数据，又能通过自定义往里面塞数据\n",
    "\n",
    "策略的多个函数都是通过context这个变量空间来共享数据\n",
    "\n",
    "https://www.myquant.cn/docs/python/python_concept#8079e2e4dad05879\n",
    "\n",
    "\n",
    "* context.data - 查询订阅数据\n",
    "\n",
    "Tips：context.data()与bar一起使用时的区别和联系\n",
    "\n",
    "以订阅‘SHSE.600519’股票日频数据为例，在on_bar()中同时输出bar和context.data()。\n",
    "\n",
    "当订阅的滑窗大小（count）为1时，bar返回的数据和context.data返回的数据是相同的\n",
    "当订阅的滑窗大小（count）大于1时，bar返回的数据为最新的一条；而context.data()返回的数据是count条，其中最后一条和bar返回的数据相同\n",
    "也就是说，无论订阅滑窗大小如何设置，bar每次只返回一条最新数据，而context.data()返回数据条数等于count，并且最后一条为最新数据。\n",
    "\n",
    "context.now\n",
    "\n",
    "context.account().positions()\n",
    "\n",
    "https://www.myquant.cn/docs/python/python_select_api#2ffd3be894353efa\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "16a0ef82",
   "metadata": {},
   "outputs": [],
   "source": [
    "#此代码只能在软件里运行\n",
    "# coding=utf-8\n",
    "from __future__ import print_function, absolute_import\n",
    "from gm.api import *\n",
    "def init(context):\n",
    "    # 同时订阅浦发银行和平安银行,数据全部到齐再触发事件\n",
    "    # wait_group是否需要等待全部代码的数据到齐再触发事件\n",
    "    # wait_group_timeout超时时间，从返回第一个bar开始计时， 默认是10s，超时后的bar不再返回\n",
    "    subscribe(symbols='SHSE.600000,SZSE.000001', frequency='1d', count=5, wait_group=True, wait_group_timeout='10s')\n",
    "def on_bar(context, bars):\n",
    "    for bar in bars:\n",
    "        print(bar['symbol'], bar['eob'])\n",
    "if __name__ == '__main__':\n",
    "    '''\n",
    "        strategy_id策略ID, 由系统生成\n",
    "        filename文件名, 请与本文件名保持一致\n",
    "        mode运行模式, 实时模式:MODE_LIVE回测模式:MODE_BACKTEST\n",
    "        token绑定计算机的ID, 可在系统设置-密钥管理中生成\n",
    "        backtest_start_time回测开始时间\n",
    "        backtest_end_time回测结束时间\n",
    "        backtest_adjust股票复权方式, 不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST\n",
    "        backtest_initial_cash回测初始资金\n",
    "        backtest_commission_ratio回测佣金比例\n",
    "        backtest_slippage_ratio回测滑点比例\n",
    "    '''\n",
    "    run(strategy_id='strategy_id',\n",
    "        filename='main.py',\n",
    "        mode=MODE_BACKTEST,\n",
    "        token='token_id',\n",
    "        backtest_start_time='2020-11-01 08:00:00',\n",
    "        backtest_end_time='2020-11-10 16:00:00',\n",
    "        backtest_adjust=ADJUST_PREV,\n",
    "        backtest_initial_cash=10000000,\n",
    "        backtest_commission_ratio=0.0001,\n",
    "        backtest_slippage_ratio=0.0001)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "446e7f7d",
   "metadata": {},
   "source": [
    "## classwork 2\n",
    "\n",
    "* 在上面的策略案例中，当前回测时间（context.now）/ 订阅代码合集（context.symbols）/ context.data - 查询订阅数据/持仓信息context.account().positions()\n",
    "\n",
    "* 通过数据事件驱动策略，在2022年第一个交易日购买两只股票：SHSE.600000,SZSE.000001，各购买50% 看一个星期后的收益\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8d3c0af3",
   "metadata": {},
   "source": [
    "## classwork 3\n",
    "\n",
    "* 编写策略，在2021全年中，当最近五天的收益率大于5%时，购买SHSE.600000 看最后收益\n",
    "\n",
    "* 上面策略中加入平仓止损。当最近5天收益率为小于-5%时全部抛出，看最后收益（order_target_volume）\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9966f153",
   "metadata": {},
   "source": [
    "## classwork 4\n",
    "\n",
    "* 编写策略，在2021全年中，SHSE.600000,SZSE.000001两只股票，对此两只股票只要有股票满足上述条件，则把全部资金用来购买，两个同时满足则各购买50%，反之则抛出"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fe37747b",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
